﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using GDFlacTool.Common;

namespace GDFlacTool.BurnAudio
{
    public partial class FormPrepareAudio : Form
    {
        private readonly string _converterPath = string.Empty;
        private readonly List<string> _convertFiles;
        private readonly List<string> _preparedFiles = new List<string>(); 

        public FormPrepareAudio(List<string> convertFiles)
        {
            InitializeComponent();

            _convertFiles = convertFiles;

            string path = Path.Combine(Application.StartupPath, "CoreConverter");
            _converterPath = Path.Combine(path, "CoreConverter.exe");
        }

        private void FormPrepareAudio_Load(object sender, EventArgs e)
        {
            lblPrepareFiles.Text = string.Format("Preparing {0} files for writing to Audio disc, please wait...", _convertFiles.Count);

            //ConvertAudioFiles();

            timer.Enabled = true;
        }

        public List<string> PreparedFiles
        {
            get { return _preparedFiles; }
        }

        #region Convert Audio File.

        private void ConvertAudioFiles()
        {
            var files = new List<string>(_convertFiles);
            string toPath = Path.GetDirectoryName(files[0]);
            string setting = GetWaveConversionSettings();
            string extension = "wav";
            string codec = "wave";
            var processes = new Process[files.Count];
            int counter = 0;

            toPath = Path.GetDirectoryName(files[0]);

            foreach (var file in files)
            {
                string fromFile = file;
                string filename = string.Format("{0}.{1}", Path.GetFileNameWithoutExtension(fromFile), extension);

                if (toPath != null)
                {
                    string toFile = Path.Combine(toPath, filename);
                    string ifile = string.Format("-infile=\"{0}\"", fromFile);
                    string ofile = string.Format("-outfile=\"{0}\"", toFile);
                    string cnvto = string.Format("-convert_to=\"{0}\"", codec);
                    string clist = string.Format("{0}", setting);

                    cnvto = string.Format("{0} -noidtag", cnvto);

                    string args = string.Format(" {0} {1} {2} {3}", ifile, ofile, cnvto, clist);

                    var proc = new Process();

                    proc.StartInfo.UseShellExecute = false;

                    proc.StartInfo.FileName = _converterPath;

                    proc.StartInfo.CreateNoWindow = true;

                    proc.StartInfo.Arguments = args;

                    processes[counter] = proc;

                    _preparedFiles.Add(toFile);

                    counter++;
                }
            }

            var cts = new CancellationTokenSource();
            var po = new ParallelOptions();

            po.CancellationToken = cts.Token;
            po.MaxDegreeOfParallelism = GetNumberOfCores();

            Task.Factory.StartNew(() =>
            {
                //if (_cancellation)
                //cts.Cancel();
            });

            try
            {
                Parallel.ForEach(processes, po, proc =>
                {
                    proc.Start();
                    proc.WaitForExit();
                    po.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (Exception e)
            {
                string msg = string.Format("There was a problem converting the selected audio files\n\n{0}", e.Message);

                MessageBox.Show(this, msg, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                DialogResult = DialogResult.Cancel;
                Close();
            }
            
            DialogResult = DialogResult.OK;
            Close();
        }

        private string GetWaveConversionSettings()
        {
            string waveCompression = string.Format("-compression=\"PCM\"");
            string waveBits = string.Format("-bits=\"16\"");
            string waveFrequency = string.Format("-freq=\"44100\"");
            string waveChannels = string.Format("-channels=\"2\"");

            var sb = new StringBuilder();
            sb.AppendFormat("{0} {1} {2} {3}", waveCompression, waveBits, waveFrequency, waveChannels);

            string setting = sb.ToString();

            setting = setting.Replace("  ", " ");
            setting = setting.Trim();

            return setting;
        }

        private int GetNumberOfCores()
        {
            int coreCount = new ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get().Cast<ManagementBaseObject>().Sum(item => int.Parse(item["NumberOfLogicalProcessors"].ToString()));

            return coreCount;
        }

        #endregion

        private void timer_Tick(object sender, EventArgs e)
        {
            ConvertAudioFiles();

            timer.Enabled = false;
        }
    }

    public class BurnFile
    {
        private string _fileName = string.Empty;
        private string _path = string.Empty;
        private string _fullPath = string.Empty;
    }
}
